package com.lsa.helpers.attic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import com.lsa.helpers.graph.EdgeNode;
import com.lsa.helpers.graph.IEdgeNode;
import com.lsa.helpers.graph.IGraph;

public class UglyAdjacencyListGraph<T, U> implements IGraph<T, U> {
	
	private List<T> vertexes;
	private List<IEdgeNode<U>> edges;
	private boolean isDirected;
	
	public UglyAdjacencyListGraph(boolean isDirected) {
		this.vertexes = new ArrayList<T>();
		this.edges = new ArrayList<IEdgeNode<U>>();
		this.isDirected = isDirected;
	}

	@Override
	public int nodeCount() {
		return this.vertexes.size();
	}

	@Override
	public int edgeCount() {
		return this.edges.size();
	}

	@Override
	public boolean isDirected() {
		return isDirected;
	}

	@Override
	public int addNode(T data) {
		vertexes.add(data);
		edges.add(null);
		return vertexes.size() - 1;
	}
	
	@Override
	public T nodeAttr(int i) {
		return vertexes.get(i);
	}

	@Override
	public void addEdge(int from, int to, U data) {
		IEdgeNode<U> edgeNode = new EdgeNode<U>(from, to, data);
		edgeNode.setNext(edges.get(from));
		edges.set(from, edgeNode);
		
		if (!isDirected){
			addEdge(to, from, data);
		}
	}

	@Override
	public Iterator<T> vertexIterator() {
		return Collections.unmodifiableCollection(vertexes).iterator();
	}

	@Override
	public Iterator<IEdgeNode<U>> edgeIterator() {
		return new Itr<U>();
	}
	
	private class Itr<U> implements Iterator<IEdgeNode<U>>{
		private int currentBucket = -1;
		private IEdgeNode<U> bucketNode;
		
		public Itr(){
			bucketNode = nextBucket();
		}
		
		@Override
		public boolean hasNext() {
			return bucketNode != null;
		}

		@Override
		public IEdgeNode<U> next() {
			IEdgeNode<U> node = bucketNode;
			IEdgeNode<U> nextNode = bucketNode.getNext();
			if (nextNode == null){
				nextNode = nextBucket();
			}
			bucketNode = nextNode;
			return node;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
		
		private IEdgeNode<U> nextBucket() {
			IEdgeNode<U> node = null;
			++currentBucket;
			for (; currentBucket < edges.size(); ++currentBucket) {
				node = (IEdgeNode<U>) edges.get(currentBucket);
				if (node != null) break;
			}
			return node;
		}
	}

	@Override
	public boolean hasEdge(int from, int to) {
		IEdgeNode<U> edgeNode = edges.get(from);
		while(edgeNode != null){
			if (edgeNode.to() == to)
				return true;
			edgeNode = edgeNode.getNext();
		}
		return false;
	}

    @Override
    public U edgeAttr(int u, int v) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<Integer> adjacencyList(int u) {
        // TODO Auto-generated method stub
        return null;
    }
}